# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : 使用LinearSVC探索鸢尾花分类(调整参数C).py
# @Author: dongguangwen
# @Date  : 2025-02-15 17:24
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score

# 1.加载数据
x, y = load_iris(return_X_y=True)
print(x.shape)
print(y.shape)

x = x[y < 2, :2]  # 取前两个特征,取前两个类别(二分类)
y = y[y < 2]
print(x.shape)
print(y.shape)

# 数据可视化
# plt.scatter(x[y == 0, 0], x[y == 0, 1], c='red')
# plt.scatter(x[y == 1, 0], x[y == 1, 1], c='blue')
# plt.show()

# 2.数据的预处理
std_scaler = StandardScaler()
x_std = std_scaler.fit_transform(x)

# 3.模型训练
model = LinearSVC(C=10)
model.fit(x_std, y)

y_pred = model.predict(x_std)
print(accuracy_score(y, y_pred))


def plot_decision_boundary_svc(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1)
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_map = ListedColormap(["#EF9A9A", "#FFF59D", "#90CAF9"])

    # plt.contourf(x0,x1,zz,linewidth=5,cmap=custom_map)
    plt.contourf(x0, x1, zz, cmap=custom_map)

    w = model.coef_[0]
    b = model.intercept_[0]
    # w0* x0 + w1* x1+ b = 0
    # =>x1 = -w0/w1 * x0 - b/w1
    plot_x = np.linspace(axis[0], axis[1], 200)
    up_y = -w[0] / w[1] * plot_x - b / w[1] + 1 / w[1]
    down_y = -w[0] / w[1] * plot_x - b / w[1] - 1 / w[1]
    up_index = (up_y >= axis[2]) & (up_y <= axis[3])
    down_index = (down_y >= axis[2]) & (down_y <= axis[3])
    plt.plot(plot_x[up_index], up_y[up_index], color="black")
    plt.plot(plot_x[down_index], down_y[down_index], color="black")


# 4.可视化
plot_decision_boundary_svc(model, axis=[-3, 3, -3, 3])
plt.scatter(x_std[y == 0, 0], x_std[y == 0, 1], c='red')
plt.scatter(x_std[y == 1, 0], x_std[y == 1, 1], c='blue')
plt.show()
